package com.whacos.modules.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whacos.common.entity.Tree;
import com.whacos.common.enums.Constant;
import com.whacos.common.utils.BuildTree;
import com.whacos.modules.system.dao.SysMenuDao;
import com.whacos.modules.system.dao.SysRoleMenuDao;
import com.whacos.modules.system.entity.SysMenu;
import com.whacos.modules.system.service.SysMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author xiongdun
 * @description SysMenuServiceImpl
 * @since 2018/11/17 17:11
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuDao sysMenuDao;
    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;

    @Cacheable(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenuByTree'")
    @Override
    public Tree<SysMenu> getTree() {
        List<Tree<SysMenu>> trees = new ArrayList<>();
        List<SysMenu> sysMenuList = this.sysMenuDao.selectList(null);
        for (SysMenu sysMenu : sysMenuList) {
            Tree<SysMenu> tree = new Tree<>();
            tree.setId(sysMenu.getId().toString());
            tree.setParentId(sysMenu.getParentId().toString());
            tree.setText(sysMenu.getMenuName());
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        return BuildTree.build(trees);
    }

    @Cacheable(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenu'")
    @Override
    public List<SysMenu> list(Wrapper<SysMenu> queryWrapper) {
        return baseMapper.selectList(queryWrapper);
    }

    @CacheEvict(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenu'")
    @Override
    public boolean updateById(SysMenu entity) {
        return super.updateById(entity);
    }

    @CacheEvict(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenu'")
    @Override
    public boolean removeById(Serializable id) {
        return super.removeById(id);
    }

    @Cacheable(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenuByRoleId' + roleId")
    @Override
    public Tree<SysMenu> getTreeByRoleId(Long roleId) {
        // 根据roleId查询权限
        List<SysMenu> sysMenuList = this.sysMenuDao.selectList(null);
        List<Long> sysMenuIdList = this.sysRoleMenuDao.listMenuIdByRoleId(roleId);
        for (SysMenu sysMenu : sysMenuList) {
            if (sysMenuIdList.contains(sysMenu.getParentId())) {
                sysMenuIdList.remove(sysMenu.getParentId());
            }
        }
        List<Tree<SysMenu>> trees = new ArrayList<>();
        List<SysMenu> sysMenus = this.sysMenuDao.selectList(null);
        for (SysMenu sysMenu : sysMenus) {
            Tree<SysMenu> tree = new Tree<>();
            tree.setId(sysMenu.getId().toString());
            tree.setParentId(sysMenu.getParentId().toString());
            tree.setText(sysMenu.getMenuName());
            Map<String, Object> state = new HashMap<>();
            Long sysMenuId = sysMenu.getId();
            if (sysMenuIdList.contains(sysMenuId)) {
                state.put("selected", true);
            } else {
                state.put("selected", false);
            }
            tree.setState(state);
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        return BuildTree.build(trees);
    }

    /**
     * @param userId
     * @return 树形菜单
     */
    @Cacheable(cacheNames = Constant.DEFAULT_CACHE_NAME, key = "'sysMenuByUserId' + userId")
    @Override
    public Tree<SysMenu> getSysMenuTreeByUserId(Long userId) {
        List<Tree<SysMenu>> trees = new ArrayList<>();
        List<SysMenu> sysMenuList = sysMenuDao.listMenuByUserId(userId);
        for (SysMenu sysMenu : sysMenuList) {
            Tree<SysMenu> tree = new Tree<>();
            tree.setId(sysMenu.getId().toString());
            tree.setParentId(sysMenu.getParentId().toString());
            tree.setText(sysMenu.getMenuName());
            Map<String, Object> attributes = new HashMap<>();
            attributes.put("url", sysMenu.getMenuUrl());
            attributes.put("icon", sysMenu.getIcon());
            tree.setAttributes(attributes);
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        return BuildTree.build(trees);
    }

    //@Cacheable(value = "sysCache")
    @Override
    public Set<String> listPermissionByUserId(Long userId) {
        List<String> permissionList = sysMenuDao.listUserPermissionsByUserId(userId);
        Set<String> permsSet = new HashSet<>();

        permissionList.forEach(permission -> {
            if (StringUtils.isNotBlank(permission)) {
                permsSet.addAll(Arrays.asList(permission.trim().split(",")));
            }
        });
        return permsSet;
    }

    @Override
    public List<Tree<SysMenu>> listSysMenuTreeByUserId(Long userId) {
        List<Tree<SysMenu>> trees = new ArrayList<>();
        List<SysMenu> sysMenuList = sysMenuDao.listMenuByUserId(userId);
        for (SysMenu sysMenu : sysMenuList) {
            Tree<SysMenu> tree = new Tree<SysMenu>();
            tree.setId(sysMenu.getId().toString());
            tree.setParentId(sysMenu.getParentId().toString());
            tree.setText(sysMenu.getMenuName());
            Map<String, Object> attributes = new HashMap<>();
            attributes.put("url", sysMenu.getMenuUrl());
            attributes.put("icon", sysMenu.getIcon());
            tree.setAttributes(attributes);
            trees.add(tree);
        }
        // 默认顶级菜单为０，根据数据库实际情况调整
        return BuildTree.buildList(trees, "0");
    }

    @Override
    public Set<String> listAllPermissions() {
        return this.sysMenuDao.listAllPermissions();
    }
}
